package ecom.shell.commandsImpl;

import ecom.beans.exception.DeviseException;
import ecom.shell.exception.InsuffisantPrivilegeException;
import ecom.beans.EcomAdminRemote;
import ecom.beans.EcomCustomerRemote;
import ecom.beans.ProductBean;
import ecom.shell.commandsImpl.OutputCommandImpl.Outputs;
import java.io.IOException;
import java.io.PrintStream;
import java.io.StringWriter;
import java.util.HashSet;
import java.util.Set;
import java.util.StringTokenizer;
import org.jdom.Attribute;
import org.jdom.Document;
import org.jdom.Element;
import org.jdom.output.Format;
import org.jdom.output.XMLOutputter;
import shell.ShellCommand;
import shell.ShellContext;

public class ProductCommandImpl implements ShellCommand {

    private ShellContext _context = null;

    public ProductCommandImpl(ShellContext context) {
        _context = context;
    }

    @Override
    public String getName() {
        return "product";
    }

    @Override
    public String getUsage() {
        return "product";
    }

    @Override
    public String getShortDescription() {
        String description = "Product commands\n";
        description += "\t-help ....................................................................get product commands description\n";
        if (true == _context.getVar("isAdmin")) {
            description += "\t-add [name] [Productcategory ID]...................................create a new product\n";
            description += "\t-add [name] [description] [urlPhoto] [Productcategory ID]..........create a new product with description and photo\n";
            description += "\t-remove [product ID]...............................................delete a product\n";
        }
        description += "\t-id [product ID]..........................................................display specified product details\n";
        description += "\t-categ [categ ID].........................................................products of a specified category\n";
        description += "\t-store [store ID].........................................................products of a specified store\n";
        description += "\t-namedesc [name] [description]............................................products fitting the specified name or description\n";
        description += "\t-price [max_price]........................................................products under the specified price\n";
        description += "\t-price [min_price] [max_price]............................................products with a price price between price1 and price2\n";
        return description;
    }

    @Override
    public String execute(String cmdline, PrintStream out, PrintStream err) throws InsuffisantPrivilegeException {
        StringBuilder result = new StringBuilder();
        EcomCustomerRemote ecomCustomerBean = (EcomCustomerRemote) _context.getVar("customerBean");
        EcomAdminRemote ecomAdminBean = (EcomAdminRemote) _context.getVar("adminBean");
        Outputs currentOutput = (Outputs) _context.getVar("output");
        String currentCurrency = (String) _context.getVar("currency");

        Set<ProductBean> products = null;

        StringTokenizer cmd = new StringTokenizer(cmdline, " ");

        cmd.nextToken();

        if (cmd.countTokens() == 0) {
            products = ecomAdminBean.getAllProducts(null);
            try {
                return printProductList(out, products, currentOutput);
            } catch (Exception ex) {
                System.err.println("Error with getting all products : " + ex.getMessage());
            }
        } else {
            String option = cmd.nextToken();

            try {
                if (option.equals("-help")) {
                    result.append(getShortDescription());
                } else if (option.equals("-add")) {
                    if (true != _context.getVar("isAdmin")) {
                        throw new InsuffisantPrivilegeException();
                    }
                    if (cmd.countTokens() == 2) {
                        String name = cmd.nextToken();
                        Long idProductcategory = Long.parseLong(cmd.nextToken());

                        Long idProduct = ecomAdminBean.createProduct(name, idProductcategory);
                        result.append("Product created with id : ").append(idProduct);
                    } else if (cmd.countTokens() == 4) {
                        String name = cmd.nextToken();
                        String description = cmd.nextToken();
                        String urlPhoto = cmd.nextToken();
                        Long idProductcategory = Long.parseLong(cmd.nextToken());

                        Long idProduct = ecomAdminBean.createEntireProduct(name, description, urlPhoto, idProductcategory);
                        result.append("Product created with id : ").append(idProduct);
                    } else {
                        err.println(EcomCommandsConstantes.INCORRECT_NUMBER_ARGS);
                    }
                } else if (option.equals("-remove")) {
                    if (true != _context.getVar("isAdmin")) {
                        throw new InsuffisantPrivilegeException();
                    }
                    if (cmd.countTokens() == 1) {
                        Long id = Long.valueOf(cmd.nextToken());
                        ecomAdminBean.removeProduct(id);
                        result.append("Product id : ").append(id).append(" deleted");
                    } else {
                        err.println(EcomCommandsConstantes.INCORRECT_NUMBER_ARGS);
                    }
                } else if (option.equals("-id")) {
                    if (cmd.countTokens() == 1) {
                        Long id = Long.valueOf(cmd.nextToken());
                        ProductBean product = ecomCustomerBean.getProductById(id);
                        return printProduct(out, product, currentOutput);
                    } else {
                        err.println(EcomCommandsConstantes.INCORRECT_NUMBER_ARGS);
                    }
                } else if (option.equals("-categ")) {
                    while (cmd.hasMoreTokens()) {
                        Long idProductcategory = Long.valueOf(cmd.nextToken().trim());
                        products = ecomCustomerBean.getProductsByIdProductcategory(idProductcategory, null);
                        return printProductList(out, products, currentOutput);
                    }
                } else if (option.equals("-store")) {
                    while (cmd.hasMoreTokens()) {
                        Long idProductstore = Long.valueOf(cmd.nextToken().trim());
                        products = ecomCustomerBean.getProductsByIdProductstore(idProductstore, null);
                        return printProductList(out, products, currentOutput);
                    }
                } else if (option.equals("-nameordesc")) {
                    String name = String.valueOf(cmd.nextToken().trim());
                    String description = String.valueOf(cmd.nextToken().trim());
                    products = ecomCustomerBean.getProductsByNameOrDesciption(name, description, null);
                    return printProductList(out, products, currentOutput);
                } else if (option.equals("-price")) {
                    Double firstPrice = Double.valueOf(cmd.nextToken().trim());
                    firstPrice = ecomCustomerBean.convertToEuro(firstPrice, currentCurrency);
                    if (cmd.hasMoreTokens()) {
                        Double secondPrice = Double.valueOf(cmd.nextToken().trim());
                        secondPrice = ecomCustomerBean.convertToEuro(secondPrice, currentCurrency);
                        products = ecomCustomerBean.getProductsByPriceInterval(firstPrice, secondPrice, null);
                    } else {
                        products = ecomCustomerBean.getProductsByByMaximumPrice(firstPrice, null);
                    }
                    return printProductList(out, products, currentOutput);
                }
            } catch (InsuffisantPrivilegeException e) {
                throw e;
            } catch (Exception ex) {
                err.println("Error with product command : " + ex.getMessage());
            }
        }
        return result.toString();
    }

    private String printProductList(PrintStream out, Set<ProductBean> products, Outputs currentOutput) throws IOException, DeviseException {
        StringBuilder res = new StringBuilder();
        if (currentOutput.equals(Outputs.XML)) {
            Element productsElement = new Element("products");
            org.jdom.Document document = new Document(productsElement);

            for (ProductBean p : products) {
                productsElement.addContent(buildXMLProductNode(p));
            }

            XMLOutputter sortie = new XMLOutputter(Format.getPrettyFormat());
            res.append(sortie.outputString(document));

        } else if (currentOutput.equals(Outputs.TEXT)) {
            for (ProductBean p : products) {
                res.append(p.toString()).append("\n");
            }
        }else {
            res.append("Output format '").append(currentOutput).append("' is known but not implementing for this command");
        }
        return res.toString();
    }

    private String printProduct(PrintStream out, ProductBean p, Outputs currentOutput) throws IOException, DeviseException {
        Set<ProductBean> list = new HashSet<ProductBean>();
        list.add(p);
        return printProductList(out, list, currentOutput);
    }

    public static Element buildXMLProductNode(ProductBean product) {
        Element productElement = new Element("product");
        Attribute id = new Attribute("id", String.valueOf(product.getIdProduct()));
        productElement.setAttribute(id);

        Element name = new Element("name");
        name.setText(product.getName());
        productElement.addContent(name);

        Element description = new Element("description");
        description.setText(product.getDescription());
        productElement.addContent(description);

        Element image = new Element("image");
        image.setText(product.getUrlPhoto());
        productElement.addContent(image);

        Element category = new Element("category");
        Attribute categId = new Attribute("id", String.valueOf(product.getIdProductCategory().getIdProductcategory()));
        category.setAttribute(categId);
        category.setText(product.getIdProductCategory().getName());
        productElement.addContent(category);

        return productElement;
    }

   
}
